<?php
/**
 *  后台代理customer的店铺管理
 * Author: lyun
 * Date: 2018/3/30
 * Created by Panxsoft.
 */

namespace App\Http\Controllers\Admin\Customer;

use App\Http\Controllers\ApiController;
use App\Http\Requests\Admin\Customer\Store\StoreIndexRequest;
use App\Http\Requests\Admin\Customer\Store\StorePatchDeleteRequest;
use App\Http\Requests\Admin\Customer\Store\StoreStoreRequest;
use App\Http\Requests\Admin\Customer\Store\StoreUpdateRequest;
use App\Models\Admin\StoreAdmin;
use App\Models\Store\Store;
use App\Models\Youzan\YouzanAuthorizer;
use App\Services\Utils\Guard;
use App\Services\Utils\Transaction;
use App\Services\Youzan\AuthorizerableService;
use Carbon\Carbon;
use GuzzleHttp\Exception\GuzzleException;

class StoreController extends ApiController
{
    const ROUTE_NAMES = [
        'index'        => 'api.admin.customer.store.index',
        'store'        => 'api.admin.customer.store.store',
        'update'       => 'api.admin.customer.store.update',
        'patch_delete' => 'api.admin.customer.store.patch.delete',
    ];

    /**
     * Display a listing of the resource.
     * @test
     *
     * @param StoreIndexRequest $request
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function index(StoreIndexRequest $request)
    {
        $this->checkCustomer();

        $stores = (new Store)
            ->where('customer_id', Guard::customerAdmin()->customer_id)
            ->columnsKeywordsOrLike([
                'name' => $request->keyword,
            ])
            ->with(['storeAdmins'])
            ->latest()
            ->paginate($request->per_page ?: 15);

        return $this->response(compact('stores'));
    }

    /**
     * @return array|\Illuminate\Http\Response
     */
    public function create()
    {
        $youzan_authorizers = (new YouzanAuthorizer)
            ->get(['id', 'youzan_store_name']);

        return $this->response(compact('youzan_authorizers'));
    }

    /**
     * Store a newly created resource in storage.
     * @test
     *
     * @param  StoreStoreRequest $request
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function store(StoreStoreRequest $request)
    {
        $this->checkCustomer();

        $store_data = $this->getStoreData($request);

        $stored = Transaction::handle(function () use ($store_data, $request) {

            /** @var Store $store */
            $store = (new Store)->create($store_data);

            $store_admin_data = $this->getStoreAdminData($store, $request);

            /** @var StoreAdmin $store_admin */
            $store_admin = StoreAdmin::create($store_admin_data);

            //分配超管角色
            $store_admin->assignRole(StoreAdmin::SUPER_MAN);

            $store->admin = $store_admin;

            return $store;
        });

        return $this->response(compact('stored'));
    }

    /**
     * @param StoreStoreRequest $request
     * @return array
     */
    private function getStoreData(StoreStoreRequest $request)
    {
        $data = [
            'customer_id' => Guard::customerAdmin()->customer_id,
            'name'        => $request->name,
            'store_img'   => $request->store_img,
            'remark'      => $request->remark,
            'email'       => $request->email ?? '',
            'phone'       => $request->phone,
            'address'     => $request->address,
            'type'        => $request->type,
            'province'    => $request->province,
            'city'        => $request->city,
            'district'    => $request->district,
        ];

        if ($request->has('has_youzan')) {
            $data['has_youzan'] = $request->has_youzan;
        }

        $address_info = $request->province . $request->city . $request->district . $request->address;
        if ($address_info) {
            $data += $this->tryQueryAddressLocation($address_info);
        }


        return $data;
    }

    /**
     * store_admins 表的数据组装
     * @param Store $store
     * @param StoreStoreRequest $request
     * @return array
     */
    private function getStoreAdminData(Store $store, StoreStoreRequest $request)
    {
        return [
            'store_id' => $store->id,
            'account'  => $request->account,
            'email'    => $request->email,
            'password' => $request->password,
            'phone'    => $request->phone,
            'born_at'  => Carbon::now(),
        ];
    }

    /**
     * Update the specified resource in storage.
     * @test
     *
     * @param  StoreUpdateRequest $request
     * @param  int $id
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function update(StoreUpdateRequest $request, $id)
    {
        $this->checkCustomer();

        /** @var Store $store */
        $store = Store::where('customer_id', Guard::customerAdmin()->customer_id)
            ->find($id);
        $this->checkItemExist($store, trans('admin.store'));

        $store_data = $this->assembleStoreUpdateData($request);

        $updated = Transaction::handle(function() use($store, $store_data){
            $updated = $store->update($store_data);

            if ($store_data['has_youzan'] === Store::NO_YOUZAN) {
                (new AuthorizerableService)->deleteYouzan($store);
            }

            return $updated;
        });

        return $this->response(compact('updated', 'store'));
    }

    /**
     * @param StoreUpdateRequest $request
     * @return array
     */
    private function assembleStoreUpdateData(StoreUpdateRequest $request)
    {
        $data = [
            'name'      => $request->name,
            'type'      => $request->type,
            'phone'     => $request->phone,
            'address'   => $request->address,
            'store_img' => $request->store_img,
            'remark'    => $request->remark,
            'province'  => $request->province,
            'city'      => $request->city,
            'district'  => $request->district,
        ];

        if (!is_null($request->is_deleted)) {
            $data['is_deleted'] = $request->is_deleted;
        }

        if ($request->has('has_youzan')) {
            $data['has_youzan'] = $request->has_youzan;
            if ((int)$request->has_youzan === Store::NO_YOUZAN) {
                $data['youzan_authorizer_id'] = Store::NO_YOUZAN;
            }
        }

        $address_info = $request->province . $request->city . $request->district . $request->address;
        if ($address_info) {
            $data += $this->tryQueryAddressLocation($address_info);
        }

        return $data;
    }

    /**
     * 关停/开启 店铺
     * @test
     *
     * @param StorePatchDeleteRequest $request
     * @param int $store_id
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function patchDelete(StorePatchDeleteRequest $request, int $store_id)
    {
        $this->checkCustomer();

        /** @var Store $store */
        $store = (new Store)
            ->where('customer_id', Guard::customerAdmin()->customer_id)
            ->find($store_id);
        $this->checkItemExist($store, trans('admin.store'));

        $updated = $store->update(['is_deleted' => $request->is_deleted]);

        return $this->response(compact('updated', 'store'));
    }

    private function tryQueryAddressLocation(string $address): array
    {
        try {
            return Store::queryAddressLocation($address) ?: [];
        } catch (GuzzleException $e) {
            return [];
        }
    }
}
